home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / binhex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  7.4 KB  |  270 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 4
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. /************************************************************************
  4.  * functions to convert files to binhex and back again
  5.  * much of this code is patterned after xbin by Dave Johnson, Brown University
  6.  * Some is lifted straight from xbin.  Our thanks to Dave & Brown.
  7.  ************************************************************************/
  8. #pragma load EUDORA_LOAD
  9. #pragma segment BinHex
  10.  
  11. /************************************************************************
  12.  * Declarations for private routines
  13.  ************************************************************************/
  14. void comp_q_crc_out(unsigned short c);
  15. short EncodeDataChar(Byte c, UPtr toSpot);
  16. int BinHexFork(short refN, UHandle dataBuffer,short dataSize,
  17.                                                                                 Handle codedBuffer,UPtr name);
  18. /************************************************************************
  19.  * six to eight bit conversion table
  20.  ************************************************************************/
  21. Byte BinHexTable[64] = {
  22.                 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
  23.                 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x30, 0x31, 0x32,
  24.                 0x33, 0x34, 0x35, 0x36, 0x38, 0x39, 0x40, 0x41,
  25.                 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
  26.                 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x50, 0x51, 0x52,
  27.                 0x53, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5a, 0x5b,
  28.                 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
  29.                 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x70, 0x71, 0x72 };
  30. unsigned long CalcCrc;
  31. Byte State86;
  32. Byte SavedBits;
  33. Byte LineLength;
  34.     
  35. #define LCODE(dc)  codedSpot += EncodeDataChar(dc,*codedBuffer+codedSpot)
  36. #define CODE(dc) do {                                                                                                     \
  37.     LCODE(dc);                                                                                                                        \
  38.     if ((Byte)dc==(Byte)0x90) LCODE(0);                                                                     \
  39.     comp_q_crc_out(dc);                                                                                                     \
  40.     } while (0)
  41. #define CODESHORT(ds) do {short copy=ds; UPtr cp=&ds;                                     \
  42.     CODE(cp[0]); CODE(cp[1]);} while(0)
  43. #define CODELONG(dl) do {long copy=dl; UPtr cp=&dl;                                         \
  44.     CODE(cp[0]); CODE(cp[1]); CODE(cp[2]); CODE(cp[3]);} while(0)
  45. /************************************************************************
  46.  * SendBinHex - send a file as BinHex data                                
  47.  ************************************************************************/
  48. int SendBinHex(short vRef,long dirId,UPtr name)
  49. {
  50.     short refN=0;
  51.     UHandle dataBuffer=nil;
  52.     UHandle codedBuffer=nil;
  53.     short dataSize;
  54.     short codedSize;
  55.     short codedSpot;
  56.     int err;
  57.     HFileInfo hfp;
  58.     Str255 scratch;
  59.     UPtr spot;
  60.     
  61.     
  62.     /*
  63.      * find the file, and get info
  64.      */
  65.     err=HGetFileInfo(vRef,dirId,name,&hfp);
  66.     if (err) {FileSystemError(BINHEX_OPEN,name,err); goto done;}
  67.     
  68.     /*
  69.      * allocate the buffers
  70.      */
  71.     codedSize = GetRLong(BUFFER_SIZE);
  72.     dataSize = codedSize/3;
  73.     if (!(dataBuffer=NuHandle(dataSize)) || !(codedBuffer=NuHandle(codedSize)))
  74.         {WarnUser(MEM_ERR,MemError()); goto done;}
  75.  
  76.     ComposeRString(scratch,BINHEX_PROG_FMT,name);
  77.     PushProgress();
  78.     ByteProgress(scratch,0,hfp.ioFlLgLen+hfp.ioFlRLgLen);
  79.  
  80.     /*
  81.      * send the header
  82.      */
  83.     GetRString(scratch,BINHEX_OUT);
  84.     if (err=SendTrans(1,scratch+1,*scratch)) goto done;
  85.         
  86.     /*
  87.      * send the file information
  88.      */
  89.     DontTranslate = True;
  90.     LineLength = 1;
  91.     State86 = CalcCrc = codedSpot = 0;
  92.     name[*name+1] = 0;
  93.     for (spot=name;*spot;spot++)
  94.         CODE(*spot);
  95.     CODE(0);
  96.     CODELONG(hfp.ioFlFndrInfo.fdType);
  97.     CODELONG(hfp.ioFlFndrInfo.fdCreator);
  98.     CODESHORT(hfp.ioFlFndrInfo.fdFlags);
  99.     CODELONG(hfp.ioFlLgLen);
  100.     CODELONG(hfp.ioFlRLgLen);
  101.     {
  102.         unsigned short tempCrc;
  103.         comp_q_crc_out(0);
  104.         comp_q_crc_out(0);
  105.         tempCrc = CalcCrc&0xffff;
  106.         CODESHORT(tempCrc);
  107.         CalcCrc = 0;
  108.     }
  109.     if (err=SendTrans(1,LDRef(codedBuffer),codedSpot)) goto done;
  110.     codedSpot = 0;
  111.     UL(codedBuffer);
  112.     
  113.     /*
  114.      * data fork
  115.      */
  116.     if (!vRef)
  117.         {FileSystemError(BINHEX_OPEN,name,0);goto done;}
  118.     if (err = FSHOpen(name,vRef,dirId,&refN,fsRdPerm))
  119.         {FileSystemError(BINHEX_OPEN,name,err); goto done;}
  120.     err = BinHexFork(refN,dataBuffer,dataSize,codedBuffer,name);
  121.     if (err) goto done;
  122.  
  123.     /*
  124.      * resource fork
  125.      */
  126.     if (refN) FSClose(refN);
  127.     refN = 0;
  128.     if (err = RFHOpen(name,vRef,dirId,&refN,fsRdPerm))
  129.         {FileSystemError(BINHEX_OPEN,name,err); goto done;}
  130.     err = BinHexFork(refN,dataBuffer,dataSize,codedBuffer,name);
  131.     if (err) goto done;
  132.  
  133.     /*
  134.      * leftovers
  135.      */
  136.     if (State86) CODE(0);
  137.     (*codedBuffer)[codedSpot++] = ':';
  138.     for (err=0;err<*NewLine;) (*codedBuffer)[codedSpot++] = NewLine[++err]; 
  139.     err=SendTrans(1,LDRef(codedBuffer),codedSpot);
  140.     
  141.     
  142. done:
  143.     if (refN) FSClose(refN);
  144.     if (dataBuffer) DisposHandle(dataBuffer);
  145.     if (codedBuffer) DisposHandle(codedBuffer);
  146.     PopProgress(False);
  147.     DontTranslate = False;
  148.     return(err);    
  149. }
  150.  
  151. /************************************************************************
  152.  * BinHexFork - send one fork of a file as BinHex data                                
  153.  ************************************************************************/
  154. int BinHexFork(short refN, UHandle dataBuffer,short dataSize,
  155.                                                                                 Handle codedBuffer,UPtr name)
  156. {
  157.     long dataEnd;
  158.     short codedSpot=0;
  159.     int err;
  160.     unsigned char *spot;
  161.     int errWas;
  162.     
  163.     do
  164.     {
  165.         dataEnd = dataSize;
  166.         err = FSRead(refN,&dataEnd,LDRef(dataBuffer));
  167.         if (!err || err==eofErr)
  168.         {
  169.             errWas = err;
  170.             for (spot = *dataBuffer; spot<*dataBuffer+dataEnd; spot++)
  171.                 CODE(*spot);
  172.             err=SendTrans(1,LDRef(codedBuffer),codedSpot);
  173.             UL(codedBuffer);
  174.             codedSpot = 0;
  175.             if (!err) err = errWas;
  176.             ByteProgress(nil,-dataEnd,0);
  177.         }
  178.         UL(dataBuffer);
  179.         if (err && err!=eofErr && !CommandPeriod)
  180.             FileSystemError(BINHEX_READ,name,err);
  181.     }
  182.     while (!err);
  183.     
  184.     if (err==eofErr)
  185.     {
  186.         {
  187.             unsigned short tempCrc;
  188.             comp_q_crc_out(0);
  189.             comp_q_crc_out(0);
  190.             tempCrc = CalcCrc&0xffff;
  191.             CODESHORT(tempCrc);
  192.             CalcCrc = 0;
  193.         }
  194.         err=SendTrans(1,LDRef(codedBuffer),codedSpot);
  195.         UL(codedBuffer);
  196.     }
  197.     
  198.     return(err==eofErr ? noErr : err);
  199. }
  200.  
  201. /************************************************************************
  202.  * EncodeDataChar - encode an 8-bit data char into a six-bit buffer
  203.  * returns the number of valid encoded characters generated
  204.  ************************************************************************/
  205. short EncodeDataChar(Byte c, UPtr toSpot)
  206. {
  207.     UPtr spotWas=toSpot;
  208.     UPtr nSpot;
  209. #define ADDNEWLINE() do {                                                                             \
  210.     LineLength = 0;                                                                                             \
  211.     for (nSpot=NewLine+1;nSpot<=NewLine+*NewLine;nSpot++)                 \
  212.         *toSpot++ = *nSpot;                                                                                 \
  213.     } while (0)
  214.  
  215.     switch (State86++)
  216.     {
  217.         case 0:
  218.             *toSpot++ = BinHexTable[(c>>2)&0x3f];
  219.             SavedBits = (c&0x3)<<4;
  220.             if (++LineLength == 64) ADDNEWLINE();
  221.             break;
  222.         case 1:
  223.             *toSpot++ = BinHexTable[SavedBits | ((c>>4)&0xf)];
  224.             SavedBits = (c&0xf)<<2;
  225.             if (++LineLength == 64) ADDNEWLINE();
  226.             break;
  227.         case 2:
  228.             *toSpot++ = BinHexTable[SavedBits | ((c>>6)&0x3)];
  229.             if (++LineLength == 64) ADDNEWLINE();
  230.             *toSpot++ = BinHexTable[c&0x3f];
  231.             if (++LineLength == 64) ADDNEWLINE();
  232.             State86 = 0;
  233.             break;
  234.     }
  235.     return(toSpot-spotWas);
  236.  
  237. /************************************************************************
  238.  * comp_q_crc_out - lifted from xbin
  239.  ************************************************************************/
  240. #define BYTEMASK 0xff
  241. #define BYTEBIT 0x100
  242. #define WORDMASK 0xffff
  243. #define WORDBIT 0x10000
  244. #define CRCCONSTANT 0x1021
  245.  
  246. void comp_q_crc_out(unsigned short c)
  247. {
  248.                 register unsigned long temp = CalcCrc;
  249.  
  250. /* Never mind why I call it WOP... */
  251. #define WOP { \
  252.                                 c <<= 1; \
  253.                                 if ((temp <<= 1) & WORDBIT) \
  254.                                                 temp = (temp & WORDMASK) ^ CRCCONSTANT; \
  255.                                 temp ^= (c >> 8); \
  256.                                 c &= BYTEMASK; \
  257.                 }
  258.                 WOP;
  259.                 WOP;
  260.                 WOP;
  261.                 WOP;
  262.                 WOP;
  263.                 WOP;
  264.                 WOP;
  265.                 WOP;
  266.                 CalcCrc = temp;
  267. }
  268.  
  269.